import dayjs from 'dayjs';
import type { Dayjs } from 'dayjs';

// 导入插件
import customParseFormat from 'dayjs/plugin/customParseFormat';
import weekday from 'dayjs/plugin/weekday';
import localeData from 'dayjs/plugin/localeData';
import weekOfYear from 'dayjs/plugin/weekOfYear';
import weekYear from 'dayjs/plugin/weekYear';
import advancedFormat from 'dayjs/plugin/advancedFormat';
import relativeTime from 'dayjs/plugin/relativeTime';
import duration from 'dayjs/plugin/duration';
import timezone from 'dayjs/plugin/timezone';
import utc from 'dayjs/plugin/utc';
import quarterOfYear from 'dayjs/plugin/quarterOfYear';

// 导入中文语言包
import 'dayjs/locale/zh-cn';

// 注册插件
dayjs.extend(customParseFormat);
dayjs.extend(weekday);
dayjs.extend(localeData);
dayjs.extend(weekOfYear);
dayjs.extend(weekYear);
dayjs.extend(advancedFormat);
dayjs.extend(relativeTime);
dayjs.extend(duration);
dayjs.extend(timezone);
dayjs.extend(utc);
dayjs.extend(quarterOfYear);

// 设置默认语言为中文
dayjs.locale('zh-cn');

// 导出配置好的 dayjs
export { dayjs };
export type { Dayjs };

/**
 * 常用日期格式常量
 */
export const DATE_FORMATS = {
  /** 年-月-日 */
  DATE: 'YYYY-MM-DD',
  /** 年-月-日 时:分:秒 */
  DATETIME: 'YYYY-MM-DD HH:mm:ss',
  /** 时:分:秒 */
  TIME: 'HH:mm:ss',
  /** 年-月-日 时:分 */
  DATETIME_SHORT: 'YYYY-MM-DD HH:mm',
  /** 月-日 */
  MONTH_DAY: 'MM-DD',
  /** 年-月 */
  YEAR_MONTH: 'YYYY-MM',
  /** 中文日期格式 */
  DATE_ZH: 'YYYY年MM月DD日',
  /** 中文完整时间格式 */
  DATETIME_ZH: 'YYYY年MM月DD日 HH:mm:ss'
} as const;

/**
 * 日期工具类
 */
export class DateUtil {
  /**
   * 格式化日期
   * @param date 日期
   * @param format 格式化字符串
   * @returns 格式化后的日期字符串
   */
  static format(date?: dayjs.ConfigType, format: string = DATE_FORMATS.DATETIME): string {
    return dayjs(date).format(format);
  }

  /**
   * 获取当前日期
   * @param format 格式化字符串
   * @returns 当前日期字符串
   */
  static now(format: string = DATE_FORMATS.DATETIME): string {
    return dayjs().format(format);
  }

  /**
   * 获取今天开始时间（00:00:00）
   */
  static startOfToday(): Dayjs {
    return dayjs().startOf('day');
  }

  /**
   * 获取今天结束时间（23:59:59）
   */
  static endOfToday(): Dayjs {
    return dayjs().endOf('day');
  }

  /**
   * 获取本月开始日期
   */
  static startOfMonth(date?: dayjs.ConfigType): Dayjs {
    return dayjs(date).startOf('month');
  }

  /**
   * 获取本月结束日期
   */
  static endOfMonth(date?: dayjs.ConfigType): Dayjs {
    return dayjs(date).endOf('month');
  }

  /**
   * 获取本年开始日期
   */
  static startOfYear(date?: dayjs.ConfigType): Dayjs {
    return dayjs(date).startOf('year');
  }

  /**
   * 获取本年结束日期
   */
  static endOfYear(date?: dayjs.ConfigType): Dayjs {
    return dayjs(date).endOf('year');
  }

  /**
   * 判断是否为今天
   * @param date 日期
   */
  static isToday(date: dayjs.ConfigType): boolean {
    return dayjs(date).isSame(dayjs(), 'day');
  }

  /**
   * 判断是否为本月
   * @param date 日期
   */
  static isThisMonth(date: dayjs.ConfigType): boolean {
    return dayjs(date).isSame(dayjs(), 'month');
  }

  /**
   * 判断是否为本年
   * @param date 日期
   */
  static isThisYear(date: dayjs.ConfigType): boolean {
    return dayjs(date).isSame(dayjs(), 'year');
  }

  /**
   * 获取两个日期之间的天数差
   * @param startDate 开始日期
   * @param endDate 结束日期
   */
  static diffInDays(startDate: dayjs.ConfigType, endDate: dayjs.ConfigType): number {
    return dayjs(endDate).diff(dayjs(startDate), 'day');
  }

  /**
   * 添加天数
   * @param date 原日期
   * @param days 要添加的天数
   */
  static addDays(date: dayjs.ConfigType, days: number): Dayjs {
    return dayjs(date).add(days, 'day');
  }

  /**
   * 减去天数
   * @param date 原日期
   * @param days 要减去的天数
   */
  static subtractDays(date: dayjs.ConfigType, days: number): Dayjs {
    return dayjs(date).subtract(days, 'day');
  }

  /**
   * 添加月份
   * @param date 原日期
   * @param months 要添加的月份数
   */
  static addMonths(date: dayjs.ConfigType, months: number): Dayjs {
    return dayjs(date).add(months, 'month');
  }

  /**
   * 减去月份
   * @param date 原日期
   * @param months 要减去的月份数
   */
  static subtractMonths(date: dayjs.ConfigType, months: number): Dayjs {
    return dayjs(date).subtract(months, 'month');
  }

  /**
   * 获取相对时间描述（如：2小时前）
   * @param date 日期
   */
  static fromNow(date: dayjs.ConfigType): string {
    return dayjs(date).fromNow();
  }

  /**
   * 获取到指定时间的相对时间描述（如：还有2小时）
   * @param date 目标日期
   */
  static toNow(date: dayjs.ConfigType): string {
    return dayjs(date).toNow();
  }

  /**
   * 解析日期字符串
   * @param dateStr 日期字符串
   * @param format 解析格式
   */
  static parse(dateStr: string, format?: string): Dayjs {
    return format ? dayjs(dateStr, format) : dayjs(dateStr);
  }

  /**
   * 获取时间戳
   * @param date 日期
   * @returns 毫秒时间戳
   */
  static timestamp(date?: dayjs.ConfigType): number {
    return dayjs(date).valueOf();
  }

  /**
   * 从时间戳创建日期
   * @param timestamp 时间戳（毫秒）
   */
  static fromTimestamp(timestamp: number): Dayjs {
    return dayjs(timestamp);
  }

  /**
   * 获取年月日对象 - 用于API调用
   * @param date 日期
   */
  static getDateParts(date?: dayjs.ConfigType): { year: string; month: string; day: string } {
    const d = dayjs(date);
    return {
      year: d.format('YYYY'),
      month: d.format('MM'),
      day: d.format('DD')
    };
  }

  /**
   * 获取当前日期的年月日 - 常用于仪表盘API调用
   */
  static getTodayParts(): { year: string; month: string; day: string } {
    return this.getDateParts();
  }

  /**
   * 获取日期范围内的所有日期
   * @param startDate 开始日期
   * @param endDate 结束日期
   * @param format 返回格式
   */
  static getDateRange(startDate: dayjs.ConfigType, endDate: dayjs.ConfigType, format = DATE_FORMATS.DATE): string[] {
    const dates: string[] = [];
    let current = dayjs(startDate);
    const end = dayjs(endDate);

    while (current.isBefore(end) || current.isSame(end, 'day')) {
      dates.push(current.format(format));
      current = current.add(1, 'day');
    }

    return dates;
  }

  /**
   * 判断日期是否有效
   * @param date 日期
   */
  static isValid(date: dayjs.ConfigType): boolean {
    return dayjs(date).isValid();
  }

  /**
   * 获取季度
   * @param date 日期
   */
  static quarter(date?: dayjs.ConfigType): number {
    return dayjs(date).quarter();
  }

  /**
   * 获取周数
   * @param date 日期
   */
  static week(date?: dayjs.ConfigType): number {
    return dayjs(date).week();
  }
}

// 导出默认实例，方便直接使用
export default dayjs;
